#include "fpc_store.h"
#include "stdint.h"
#include "stdbool.h"
#include <stdlib.h>
#include "device.h"

/* 调试打印接口 */
#define FPC_STORE_LOG(format, ...)          OSAL_LOG(C_YELLOW format C_NONE, ##__VA_ARGS__)
#define __FPC_STORE_LOG(format, ...)        __OSAL_LOG(format, ##__VA_ARGS__)

/* 定义虚拟硬件接口 */
#define VHW_FINGER_RW                  		vFLASH_1

#define PRINTF_MAP          0
#define PRINTF_VERF_LIST    0

#define FPC_DATA_SIZE       (14 * 1024)
#define FLASH_ROW_SIZE      (4096)
#define ROWSIZE				(4096)

#define FPC_START_ADDR		0
#define FPC_DATA_ADDR       (FPC_START_ADDR + sizeof(FpcTable_t))                           
#define FPC_DATA            ((Fpc_Data_t*)FPC_DATA_ADDR)			//指纹模板数据的起始地址
#define FPC_TABLE           ((FpcTable_t *)FPC_START_ADDR)			//指纹模板索引数据的起始地址
#define MAP_QTY_FPC         ((FPC_MAX_NUM / 8) + 1)					//索引区大小

#pragma pack(1)
/*单个指纹模板的数据*/
typedef struct
{
    uint32_t    TimeStamp;                              //时间戳
    uint16_t    TempNum;                                //模板ID
    uint16_t    len;                                    //模板数据长度
    uint32_t    crc;                                    //校验值
    uint8_t     data[FPC_DATA_SIZE - 12];               //模板数据
} FpcData_t;

/*初始化标志区和索引区*/
typedef struct
{
    uint8_t     initflag;                               //初始化标志
    uint8_t     reserve1[ROWSIZE - 1];           		//保留
    uint8_t     index[32];                              //索引
    uint32_t    crc;                                    //校验
    uint8_t     reserve[ROWSIZE - 32 - 4];       		//保留
    uint8_t     index_backup[32];                       //备份索引
    uint32_t    crc2;                                   //备份索引校验
    uint8_t     reserve_backup[ROWSIZE - 32 - 4];		//备份保留
} FpcTable_t;

/*指纹模板数据*/
typedef struct
{
    FpcData_t fpcdata[FPC_MAX_NUM];
} Fpc_Data_t;

#pragma pack()

static uint8_t g_FpcMap[MAP_QTY_FPC]; //指纹模板位图
static size_t temp_max_len = 0;

__EFRAM static uint32_t maxTimeCount = 0;	//记录指纹最大的时间因子

#if (PRINTF_VERF_LIST) && defined(PRINTF_VERF_LIST)
static void printf_bit(char *message, uint8_t *buf, uint32_t size)
{
    FPC_STORE_LOG("%s (%d Bytes):\r\n", message, size);

    for (uint32_t index = 0; index < size; index++)
    {
        for (uint32_t i = 0; i < 8; i++)
        {
            printf("%d ", (buf[index] >> i) & 0x01);
        }
        printf("\r\n");
    }
    FPC_STORE_LOG("\r\n\r\n");
}
#endif

/* 获取指纹的最大时间因子 */
static uint32_t Fpc_Get_Counter(void)
{
	maxTimeCount = maxTimeCount + 1;
	FPC_STORE_LOG("maxTimeCount = %d\r\n", maxTimeCount);
	return maxTimeCount;
}

/* 设置指纹的最大时间因子 */
static void Fpc_Set_Counter(uint32_t timeMax)
{
	maxTimeCount = timeMax;
	FPC_STORE_LOG("maxTimeCount = %d\r\n", maxTimeCount);
}

static bool fpc_flash_read(uint32_t addr, uint8_t *out_buf, uint32_t len)
{
	Device_Read(VHW_FINGER_RW, out_buf, len, addr);
    return true;
}

static bool fpc_flash_write(uint32_t address, uint8_t *WriteBuffer, uint32_t txSize)
{
	int8_t ret = Device_Write(VHW_FINGER_RW, WriteBuffer, txSize, address);
    return (ret == 0) ? true : false;
}

/*查找ID是否占用*/
static uint8_t fpc_find_id(uint16_t id)
{
    uint8_t map = 0;

    if (id >= FPC_MAX_NUM)
        return 0;

    map = g_FpcMap[id / 8];

    if ((map & (1 << (id % 8))) == 0)
    {
        return 1; //该ID未占用
    }
    return 0;
}

/**
  * @brief  查找空闲的指纹ID号码
  * @note   
  *         

  * @return ：空闲ID号码
  */
static uint8_t fpc_find_freespace(void)
{
    uint8_t index = 0xff;
    for (int i = 0; i < FPC_MAX_NUM; i++)
    {
        if (fpc_find_id(i) == 1)
        {
            index = i;
            break;
        }
    }
    return index;
}

static uint16_t fpc_read_temp_len(uint16_t index_id)
{
    if (index_id >= FPC_MAX_NUM)
        return 0;
    uint16_t len = 0;
    fpc_flash_read((uint32_t)(&FPC_DATA->fpcdata[index_id].len), (uint8_t *)&len, sizeof(uint16_t));
    //FPC_STORE_LOG("temp len :%d\r\n",len);
    return len;
}

/**
  * @brief  ：计算缓存区XOR校验
  * @note   
  * param  buf：缓存区       
  * param  size：缓存区大小
  * @return ：返回校验值
  */
static uint32_t cal_xor(uint8_t *buf, uint32_t size)
{
    uint32_t len = size / 4;
    uint32_t len2 = size % 4;
    uint8_t ibuf[4];
    memset(ibuf, 0, 4);
    for (uint32_t i = 0; i < len; i++)
    {
        ibuf[0] ^= buf[i];
        ibuf[1] ^= buf[len + i];
        ibuf[2] ^= buf[len * 2 + i];
        ibuf[3] ^= buf[len * 3 + i];
    }

    for (uint32_t i = 0; i < len2; i++)
    {
        ibuf[3] ^= buf[len * 4 + i];
    }
    return (uint32_t)((ibuf[0] << 24) | (ibuf[1] << 16) | (ibuf[2] << 8) | (ibuf[3] & 0xff));
}

/**
  * @brief  ：更新指纹模板索引
  * @note   
  * param  fpcid：索引ID       
  * param  add_del：true 添加索引  false 删除索引
  * @return ：成功返回true ,失败返回false
  */
static bool updata_index(uint16_t fpcid, bool add_del)
{
    if (fpcid >= FPC_MAX_NUM)
    {
        return false;
    }

    uint8_t index[36];
#ifdef FINGER_INDEX_SAVE_EEPROM
    OSAL_NvRead(OSAL_OFFSET(NvFinger_stu_t,index), index, 36);
#else
    fpc_flash_read((uint32_t)&FPC_TABLE->index, index, 36);             //读取索引区
    if (fpc_flash_write((uint32_t)&FPC_TABLE->index_backup, index, 36)) //写入备份区
    {
        uint8_t cbuf[36];
        fpc_flash_read((uint32_t)&FPC_TABLE->index_backup, cbuf, 36); //读取备份索引区
        if (memcmp(index, cbuf, 36) != 0)                             //比对内容
        {
            FPC_STORE_LOG("index_backup write is fail!\r\n");
            return false;
        }
    }
    else
    {
        FPC_STORE_LOG("index_backup write is fail!\r\n");
        return false;
    }
#endif

    if (add_del)
    {
        index[fpcid / 8] |= (1 << (fpcid % 8)); //添加索引
    }
    else
    {
        index[fpcid / 8] &= (~(1 << (fpcid % 8))); //删除索引
    }

    uint32_t crc = cal_xor(index, MAP_QTY_FPC);
    memcpy(&index[32], (uint8_t *)&crc, sizeof(uint32_t)); //更新CRC校验值

#ifdef FINGER_INDEX_SAVE_EEPROM

    if (OSAL_NvWrite(OSAL_OFFSET(NvFinger_stu_t,index), index, 36) == SUCCESS)
    {
        g_FpcMap[fpcid / 8] = index[fpcid / 8]; //更新内存中的索引    
    }
    else
    {
        FPC_STORE_LOG("index write is fail!\r\n");
        return false;
    }

#else
    if (fpc_flash_write((uint32_t)&FPC_TABLE->index, index, 36)) //写入索引区
    {
        uint8_t mbuf[36];
        FPC_STORE_LOG("index addr : 0x%08X\r\n",(uint32_t)&FPC_TABLE->index);
        fpc_flash_read((uint32_t)&FPC_TABLE->index, mbuf, 36); //读取索引区
        if (memcmp(index, mbuf, 36) != 0)                      //比对内容
        {
            FPC_STORE_LOG("index write is fail!\r\n");
            return false;
        }
        else
        {
            g_FpcMap[fpcid / 8] = index[fpcid / 8]; //更新内存中的索引
        }
    }
    else
    {
        FPC_STORE_LOG("index write is fail!\r\n");
        return false;
    }
#endif
    return true;
}

/**
  * @brief  ：验证成功是更新索引
  * @note   
  * param  old_id:旧ID       
  * param  new_id:新ID
  * @return ：成功返回true ,失败返回false
  */
static bool verify_update_index(uint16_t old_id, uint16_t new_id)
{
    if ((old_id >= FPC_MAX_NUM) || (new_id >= FPC_MAX_NUM))
    {
        return false;
    }

    uint8_t index[36];
#ifdef FINGER_INDEX_SAVE_EEPROM
    OSAL_NvRead(OSAL_OFFSET(NvFinger_stu_t,index), index, 36);
#else
    fpc_flash_read((uint32_t)&FPC_TABLE->index, index, 36);             //读取索引区
    if (fpc_flash_write((uint32_t)&FPC_TABLE->index_backup, index, 36)) //写入备份区
    {
        uint8_t cbuf[36];
        fpc_flash_read((uint32_t)&FPC_TABLE->index_backup, cbuf, 36); //读取备份索引区
        if (memcmp(index, cbuf, 36) != 0)                             //比对内容
        {
            FPC_STORE_LOG("index_backup write is fail!\r\n");
            return false;
        }
    }
    else
    {
        FPC_STORE_LOG("index_backup write is fail!\r\n");
        return false;
    }
#endif
    index[old_id / 8] &= (~(1 << (old_id % 8))); //删除旧索引
    index[new_id / 8] |= (1 << (new_id % 8));    //添加新索引

    uint32_t crc = cal_xor(index, MAP_QTY_FPC);
    memcpy(&index[32], (uint8_t *)&crc, sizeof(uint32_t)); //更新CRC校验值
#ifdef FINGER_INDEX_SAVE_EEPROM

    if (OSAL_NvWrite(OSAL_OFFSET(NvFinger_stu_t,index), index, 36) == SUCCESS)
    {
        g_FpcMap[old_id / 8] = index[old_id / 8];
        g_FpcMap[new_id / 8] = index[new_id / 8]; //更新内存中的索引
    }
    else
    {
        FPC_STORE_LOG("index_backup write is fail!\r\n");
        return false;
    }

#else
    if (fpc_flash_write((uint32_t)&FPC_TABLE->index, index, 36)) //写入索引区
    {
        uint8_t mbuf[36];
        fpc_flash_read((uint32_t)&FPC_TABLE->index, mbuf, 36); //读取索引区
        if (memcmp(index, mbuf, 36) != 0)                      //比对内容
        {
            FPC_STORE_LOG("index_backup write is fail!\r\n");
            return false;
        }
        else
        {
            g_FpcMap[old_id / 8] = index[old_id / 8];
            g_FpcMap[new_id / 8] = index[new_id / 8]; //更新内存中的索引
        }
    }
    else
    {
        FPC_STORE_LOG("index_backup write is fail!\r\n");
        return false;
    }
#endif
    return true;
}

/**
  * @brief  ：输出所有有效模板的ID号
  * @note   
  * param   ：存储ID的数组指针        

  * @return ：有效的指纹模板数量
  */
static uint16_t fpc_out_temp_num(uint16_t *index_id)
{
    uint16_t num = 0;

    for (uint16_t i = 0; i < MAP_QTY_FPC; i++)
    {
        for (uint16_t j = 0; j < 8; j++)
        {
            if ((g_FpcMap[i] & (1 << j)) != 0)
            {
                index_id[num] = i * 8 + j;
                num++;
            }
        }
    }
    return num; //有效的fpc模板数量
}

/**
  * @brief  建立索引到内存中
  * @note   
  *         
  * @param  
  * @param  
  * @return 
  */
static void fpc_creat_index(void)
{
    uint8_t index[36];
#ifdef FINGER_INDEX_SAVE_EEPROM
    OSAL_NvRead(OSAL_OFFSET(NvFinger_stu_t,index), index, 36);
    uint32_t *crc = (uint32_t *)&index[32];
    if (*crc == cal_xor(index, MAP_QTY_FPC))
    {
        memcpy((void *)g_FpcMap, index, MAP_QTY_FPC);    
    }
    else
    {
        FPC_STORE_LOG("index crc is error!\r\n");    
    }
#else
    uint8_t index2[36];
    uint32_t *crc1, *crc2;
    fpc_flash_read((uint32_t)(&FPC_TABLE->index), index, 36);         //读取索引
    fpc_flash_read((uint32_t)(&FPC_TABLE->index_backup), index2, 36); //读取备份索引
    crc1 = (uint32_t *)&index[32];
    crc2 = (uint32_t *)&index2[32];
    if (*crc1 != cal_xor(index, MAP_QTY_FPC)) //比对校验值
    {
        if (*crc2 == cal_xor(index2, MAP_QTY_FPC))
        {
            fpc_flash_write((uint32_t)(&FPC_TABLE->index), index2, 36);
            memcpy((void *)g_FpcMap, index2, MAP_QTY_FPC);
        }
        FPC_STORE_LOG("index crc is error!\r\n");
    }
    else
    {
        memcpy((void *)g_FpcMap, index, MAP_QTY_FPC);
    }
#endif

#if (PRINTF_MAP) && defined(PRINTF_MAP)
    __FPC_STORE_LOG("line = %05d,", __LINE__);
    printf_bit("CREAT FPC MAP ", (uint8_t *)g_FpcMap, MAP_QTY_FPC);
#endif
}

bool fpc_store_init(size_t max_len, VerifList_t *verif_list)
{
    temp_max_len = max_len;
#ifdef FINGER_INDEX_SAVE_EEPROM
    uint8_t fpc_store_flag = 0;
    OSAL_NvRead(OSAL_OFFSET(NvFinger_stu_t,fpc_store_flag), &fpc_store_flag, 1);/* 读初始化标志 */
    if (fpc_store_flag != 0xAA)
    {
        uint8_t tmp[37] = {0};
        tmp[0] = 0xAA;
        uint32_t crc = cal_xor(&tmp[1], MAP_QTY_FPC);
        memcpy(&tmp[33], (uint8_t *)&crc, sizeof(uint32_t));
        memset((void *)g_FpcMap, 0, MAP_QTY_FPC);
        OSAL_NvWrite(OSAL_OFFSET(NvFinger_stu_t,fpc_store_flag), tmp, 37);
    }
    else
    {
        memset((void *)g_FpcMap, 0, MAP_QTY_FPC);
        fpc_creat_index(); //创建索引表    
    }
#else
    uint8_t flag;
    uint8_t tmp[36];
    uint8_t initdata = 0XAA;
    uint32_t crc;

    memset(tmp, 0, 36);
	
    fpc_flash_read((uint32_t)(&FPC_TABLE->initflag), &flag, 1);

	FPC_STORE_LOG("flag = 0x%02x!\r\n", flag);
    if (flag != 0xAA) //检测初始化标志
    {
        crc = cal_xor(tmp, MAP_QTY_FPC);
        FPC_STORE_LOG("crc is 0x%08X!\r\n", crc);
        memcpy(&tmp[32], (uint8_t *)&crc, sizeof(uint32_t));
        fpc_flash_write((uint32_t)(&FPC_TABLE->index), tmp, 36);         //初始化索引区
        fpc_flash_write((uint32_t)(&FPC_TABLE->index_backup), tmp, 36);  //初始化备份索引区
		
		fpc_flash_write((uint32_t)(&FPC_TABLE->initflag), &initdata, 1); //写入初始化标志
        memset((void *)g_FpcMap, 0, MAP_QTY_FPC);
    }
    else
    {
        memset((void *)g_FpcMap, 0, MAP_QTY_FPC);
        fpc_creat_index(); //创建索引表
    }
#endif

    uint16_t len = fpc_read_verify_num(verif_list);
    if (len > 0)
    {
        if (verif_list->list[0].time_stamp > verif_list->list[1].time_stamp)//0号为管理指纹
        {
			Fpc_Set_Counter(verif_list->list[0].time_stamp);//设置时间因子
        }  
        else
        {
            Fpc_Set_Counter(verif_list->list[1].time_stamp);//设置时间因子
        }    
    }
    return true;
}

/**
  * @brief  保存模板
  * @note   
  *         
  * @param  temp：指纹模板
  * @param  fpc_num：指纹编号
  * @param  save_type：true 保持添加指纹，false保存更新指纹
  * @return 
  */
bool fpc_save_temp(const fpc_bep_template_t **temp,uint16_t fpc_num, bool save_type)
{
    if (*temp == NULL || fpc_num >= FPC_MAX_NUM - 1)
        return false;
    size_t size;
    fpc_bep_result_t res;
    FpcData_t *fpcdata = malloc(sizeof(FpcData_t));
    if (fpcdata == NULL)
        return false;
    res = fpc_bep_template_get_size(*temp, &size); //获取模板数据大小
	FPC_STORE_LOG("size: %d\r\n", size);
    if (res != FPC_BEP_RESULT_OK)
    {
        FPC_STORE_LOG("fpc_bep_template_get_size is error!\r\n");
        if (fpcdata)
            free(fpcdata);
        fpc_bep_template_delete((fpc_bep_template_t **)temp);
        return false;
    }
    res = fpc_bep_template_serialize(*temp, fpcdata->data, size); //模板串行化
    if (res != FPC_BEP_RESULT_OK)
    {
        FPC_STORE_LOG("fpc_bep_template_serialize is error!\r\n");
        if (fpcdata)
            free(fpcdata);
        fpc_bep_template_delete((fpc_bep_template_t **)temp);
        return false;
    }
    fpcdata->len = (uint16_t)size;
    uint32_t crc = cal_xor(fpcdata->data, size); //计算CRC值

    FPC_STORE_LOG("crc = 0x%08X,size = %d!\r\n", crc, size);

    fpcdata->crc = crc;
    fpcdata->TimeStamp = Fpc_Get_Counter();//time_cnt;更新时间因子
    fpcdata->TempNum = fpc_num;
    FPC_STORE_LOG("fpcdata.TempNum = %d,fpcdata.TimeStamp = %d\r\n", fpcdata->TempNum, fpcdata->TimeStamp);

	uint16_t id[FPC_MAX_NUM];
	SortList_t mlist[FPC_MAX_NUM];
    uint16_t len = fpc_out_temp_num(id);

    uint8_t freeid = 0xff;
    uint8_t old_id = 0xff;
    for (uint16_t i = 0; i < len; i++)
    {
        fpc_flash_read((uint32_t)(&FPC_DATA->fpcdata[id[i]].TempNum), (uint8_t *)&mlist[i].fpc_num, sizeof(uint16_t)); //读指纹编号
        mlist[i].index_id = id[i];
    }
    for (uint16_t j = 0; j < len; j++) //查找指纹索引,覆盖存储
    {
        if (mlist[j].fpc_num == fpc_num)
        {
            freeid = mlist[j].index_id;
            old_id = freeid;
            break;
        }
    }
    if (save_type)
    {
        if (freeid == 0xff) //没找到编号，重新申请空间
        {
            freeid = fpc_find_freespace();
        }
    }
    else//更新指纹时
    {
        freeid = fpc_find_freespace();    //直接重新申请空间
    }
    if (freeid != 0xff)
    {
        if (fpc_flash_write((uint32_t)(&FPC_DATA->fpcdata[freeid]), (uint8_t *)fpcdata, sizeof(FpcData_t))) //保存模板
        {
            if (save_type)
            {
#if (PRINTF_MAP) && defined(PRINTF_MAP)
                FPC_STORE_LOG("line = %05d,", __LINE__);
                printf_bit("CREAT FPC MAP ", (uint8_t *)g_FpcMap, MAP_QTY_FPC);
#endif
                if (updata_index(freeid, true))
                {
                    FPC_STORE_LOG("save temp addr = 0x%08X", (uint32_t)(&FPC_DATA->fpcdata[freeid]));
#if (PRINTF_MAP) && defined(PRINTF_MAP)
                    FPC_STORE_LOG("line = %05d,", __LINE__);
                    printf_bit("CREAT FPC MAP ", (uint8_t *)g_FpcMap, MAP_QTY_FPC);
#endif
                }
                else
                {
                    FPC_STORE_LOG("updata_index is error!\r\n");
                    if (fpcdata) free(fpcdata);
                    fpc_bep_template_delete((fpc_bep_template_t **)temp);
                    return false;
                }
            }
            else
            {
#if (PRINTF_MAP) && defined(PRINTF_MAP)
                    FPC_STORE_LOG("line = %05d,", __LINE__);
                    printf_bit("CREAT FPC MAP ", (uint8_t *)g_FpcMap, MAP_QTY_FPC);
#endif
                if (verify_update_index(old_id,freeid))
                {
#if (PRINTF_MAP) && defined(PRINTF_MAP)
                    FPC_STORE_LOG("line = %05d,", __LINE__);
                    printf_bit("CREAT FPC MAP ", (uint8_t *)g_FpcMap, MAP_QTY_FPC);
#endif
                    FPC_STORE_LOG("verify_update_index,old index :%d,new index:%d\r\n",old_id,freeid);
                }
                else
                {
                    FPC_STORE_LOG("verify_update_index is error!\r\n");
                    if (fpcdata) free(fpcdata);
                    fpc_bep_template_delete((fpc_bep_template_t **)temp);
                    return false;    
                }    
            }
        }
        else
        {
            FPC_STORE_LOG("fpc_save_temp error\r\n");
            if (fpcdata) free(fpcdata);
            fpc_bep_template_delete((fpc_bep_template_t **)temp);
            return false;
        }
    }
    if (fpcdata) 
		free(fpcdata);
    res = fpc_bep_template_delete((fpc_bep_template_t **)temp);
    if (res != FPC_BEP_RESULT_OK)
    {
        FPC_STORE_LOG("res = %d\r\n",res);   
    }
    return true;
}

bool fpc_del_num(uint16_t start_num, uint16_t nums)
{
    uint16_t id[FPC_MAX_NUM];
    uint16_t len = fpc_out_temp_num(id);
    SortList_t mlist[FPC_MAX_NUM];
    uint8_t index[36];
    memset(index, 0, 36);
    memcpy(index, g_FpcMap, MAP_QTY_FPC);

    FPC_STORE_LOG("DEL ID = %d,NUM = %d\r\n", start_num, nums);

    for (uint16_t i = 0; i < len; i++)
    {
        fpc_flash_read((uint32_t)(&FPC_DATA->fpcdata[id[i]].TempNum), (uint8_t *)&mlist[i].fpc_num, sizeof(uint16_t));
        mlist[i].index_id = id[i];
    }

    for (uint16_t j = 0; j < len; j++)
    {
        if (mlist[j].fpc_num >= start_num && mlist[j].fpc_num < (start_num + nums))
        {
            index[(mlist[j].index_id) / 8] &= (~(1 << ((mlist[j].index_id) % 8)));
        }
    }

    uint32_t crc = cal_xor(index, MAP_QTY_FPC);     //计算CRC校验值
    memcpy(&index[32], (uint8_t *)&crc, sizeof(uint32_t)); //更新CRC值

#ifdef FINGER_INDEX_SAVE_EEPROM
    if (OSAL_NvWrite(OSAL_OFFSET(NvFinger_stu_t,index), index, 36) == SUCCESS)
    {
        memcpy(g_FpcMap, index, MAP_QTY_FPC); //更新内存中的索引
        return true;
    }
    else
    {
        FPC_STORE_LOG("index write is fail!\r\n");
    }
#else  
    uint8_t index2[36];
    fpc_flash_read((uint32_t)&FPC_TABLE->index, index2, 36);             //读取索引区
    if (fpc_flash_write((uint32_t)&FPC_TABLE->index_backup, index2, 36)) //写入备份区
    {
        uint8_t cbuf[36];
        fpc_flash_read((uint32_t)&FPC_TABLE->index_backup, cbuf, 36); //读取备份索引区
        if (memcmp(index2, cbuf, 36) != 0)                            //比对内容
        {
            FPC_STORE_LOG("index_backup write is fail!\r\n");
        }
        else
        {
            if (fpc_flash_write((uint32_t)&FPC_TABLE->index, index, 36)) //写入索引区
            {
                uint8_t mbuf[36];
                fpc_flash_read((uint32_t)&FPC_TABLE->index, mbuf, 36); //读取索引区
                if (memcmp(index, mbuf, 36) != 0)                      //比对内容
                {
                    FPC_STORE_LOG("index_backup write is fail!\r\n");
                }
                else
                {
                    memcpy(g_FpcMap, index, MAP_QTY_FPC); //更新内存中的索引
                    return true;
                }
            }
            else
            {
                FPC_STORE_LOG("index_backup write is fail!\r\n");
            }
        }
    }
    else
    {
        FPC_STORE_LOG("index_backup write is fail!\r\n");
    }
#endif
    return false;
}

bool fpc_store_empty(void)
{
    uint8_t tmp[36];
    memset(tmp, 0x00, 36);
    uint32_t crc = cal_xor(tmp, MAP_QTY_FPC);
    memcpy(&tmp[32], (uint8_t *)&crc, sizeof(uint32_t));
#ifdef FINGER_INDEX_SAVE_EEPROM
    if (OSAL_NvWrite(OSAL_OFFSET(NvFinger_stu_t,index), tmp, 36) == SUCCESS)
    {
        memset((void *)g_FpcMap, 0, MAP_QTY_FPC);
        return true;
    }
#else
    if (fpc_flash_write((uint32_t)(&FPC_TABLE->index), tmp, 36) && fpc_flash_write((uint32_t)(&FPC_TABLE->index_backup), tmp, 36))
    {
        memset((void *)g_FpcMap, 0, MAP_QTY_FPC);
        return true;
    }
#endif
    return false;
}

bool fpc_read_temp(fpc_bep_template_t **temp, uint16_t index_id)
{
    if (temp == NULL || index_id >= FPC_MAX_NUM)
        return false;

    uint16_t tmplen;
    fpc_bep_result_t res;
    
    tmplen = fpc_read_temp_len(index_id); //  读取模板数据长度
    if (tmplen != temp_max_len)
    {
        FPC_STORE_LOG("templen = %d \r\n", tmplen);
        return false;
    }
    FpcData_t *fpcdata = malloc(sizeof(FpcData_t));
    fpc_flash_read((uint32_t)(&FPC_DATA->fpcdata[index_id].crc), (uint8_t *)&fpcdata->crc, tmplen + 4); //读取模板
    uint32_t crc = fpcdata->crc;
    uint32_t crc2 = cal_xor(fpcdata->data, tmplen);
    if (crc != crc2)
    {
        updata_index(index_id, false); //模板数据校验出错，删除对应索引
        FPC_STORE_LOG("The temp data crc is error , temp id = %d\r\n", index_id);
        if (fpcdata) free(fpcdata);
        return false;
    }

    res = fpc_bep_template_deserialize(temp, fpcdata->data, tmplen, FPC_BEP_DISABLE_MEM_RELEASE);

    if (FPC_BEP_RESULT_OK != res)
    {
        FPC_STORE_LOG("fpc_bep_template_deserialize is error,error code = %d!\r\n", res);
        if (fpcdata) free(fpcdata);
        return false;
    }
    if (fpcdata) free(fpcdata);
    return true;
}

/* 使用冒泡排序对索引进行升序排序,从第0个元素开始 */
void fpc_num_list_sort_rise(VerifList_t *verif_list)
{
	uint16_t i,j;
	SortList_t sortlisttemp;
	memset(&sortlisttemp, 0, sizeof(sortlisttemp));
	for (i = 0; i < verif_list->size - 1; i++)
    {
		for (j = i + 1; j < verif_list->size; j++)
		{
			if(verif_list->list[j].fpc_num < verif_list->list[i].fpc_num)
			{
				memcpy(&sortlisttemp, &verif_list->list[i], sizeof(SortList_t));
				memcpy(&verif_list->list[i], &verif_list->list[j], sizeof(SortList_t));
				memcpy(&verif_list->list[j], &sortlisttemp, sizeof(SortList_t));
			}
		}
	}
}

/* 使用冒泡排序对时间戳进行降序排序,注意是从第1个元素开始排序,管理指纹始终放在第0个不参与排序 */
void fpc_time_stamp_list_sort_drop(VerifList_t *verif_list)
{
	uint16_t i,j;
	SortList_t sortlisttemp;
	memset(&sortlisttemp, 0, sizeof(sortlisttemp));
	for (i = 1; i < verif_list->size - 1; i++)
    {
		for (j = i + 1; j < verif_list->size; j++)
		{
			if(verif_list->list[j].time_stamp > verif_list->list[i].time_stamp)
			{
				memcpy(&sortlisttemp, &verif_list->list[i], sizeof(SortList_t));
				memcpy(&verif_list->list[i], &verif_list->list[j], sizeof(SortList_t));
				memcpy(&verif_list->list[j], &sortlisttemp, sizeof(SortList_t));
			}
		}
	}
}

/**
  * @brief  读取验证号码，存到verif_list中排序
  * @note   
  *         
  * @param  index_id ：存有指纹索引ID的数组
  * @param  verif_list：验证列表
  * @return 有效模板个数
  */
uint16_t fpc_read_verify_num(VerifList_t *verif_list)
{
    uint16_t index_id[FPC_MAX_NUM];
    uint16_t nums = fpc_out_temp_num(index_id);
#if (PRINTF_VERF_LIST) && defined(PRINTF_VERF_LIST)	
	FPC_STORE_LOG("nums = %d\r\n", nums);
#endif	
    for (uint16_t i = 0; i < nums; i++)
    {
        fpc_flash_read((uint32_t)(&FPC_DATA->fpcdata[index_id[i]].TimeStamp), (uint8_t *)&verif_list->list[i].time_stamp, sizeof(uint32_t));
        fpc_flash_read((uint32_t)(&FPC_DATA->fpcdata[index_id[i]].TempNum), (uint8_t *)&verif_list->list[i].fpc_num, sizeof(uint16_t));
        verif_list->list[i].index_id = index_id[i];
#if (PRINTF_VERF_LIST) && defined(PRINTF_VERF_LIST)
        FPC_STORE_LOG("list[%d],time_stamp:%d,fpc_num:%d,index_id:%d\r\n",i,verif_list->list[i].time_stamp,verif_list->list[i].fpc_num,verif_list->list[i].index_id);
#endif
    }
    verif_list->size = nums;

    FPC_STORE_LOG("qsort\r\n");
	fpc_num_list_sort_rise(verif_list);
	fpc_time_stamp_list_sort_drop(verif_list);
#if (PRINTF_VERF_LIST) && defined(PRINTF_VERF_LIST)
    for (uint16_t i = 0; i < nums; i++)
    {
        FPC_STORE_LOG("list[%d],time_stamp:%d,fpc_num:%d,index_id:%d\r\n",i,verif_list->list[i].time_stamp,verif_list->list[i].fpc_num,verif_list->list[i].index_id);    
    }
#endif
    return nums;
}

//根据指纹号码读模板
bool fpc_read_temp_finger_num(VerifList_t *verif_list,fpc_bep_template_t **temp, uint16_t finger_num)
{
    uint16_t nums = fpc_read_verify_num(verif_list);
    if (nums == 0)
    {
        return false;
    }

    uint16_t index_id = 0xffff;

    for (int i=0;i<nums;i++)
    {
        if (verif_list->list[i].fpc_num == finger_num)
        {
            index_id = verif_list->list[i].index_id;
            break;
        }    
    }

    if (index_id == 0xffff)
    {
        return false;
    }
    else
    {
        return fpc_read_temp(temp,index_id);  
    }
}

void fpc_store_read_index(uint8_t *out,uint16_t out_len,VerifList_t *verif_list)
{
    memset(out,0,out_len);
    uint16_t num = fpc_read_verify_num(verif_list);
    for (uint16_t i=0;i<num;i++)
    {
        // logout("fpc_num:%d\r\n",verif_list->list[i].fpc_num);
        out[verif_list->list[i].fpc_num / 8] |= (1 << (verif_list->list[i].fpc_num % 8));
    }
}
